package com.om.deadlock;

public class Philosopher {
	public static final int EAT_DEADLINE = 20;
	private int starvationTimer = 0;
	private boolean isAlive = true;
	private Fork leftFork;
	private Fork rightFork;
	private State state = State.THINKING;

	enum State {
		THINKING, WAITING, EATING
	}

	private void stillWaitingToEat() {
		if (--starvationTimer <= 0)
			die();
	}

	private void die() {
//		System.out.printf("Dead: %d - state %s\n", myNumber, state.name());
		isAlive = false;
	}

	public Philosopher(Fork left, Fork right) {
		this.leftFork = left;
		this.rightFork = right;
	}

	static int threadNumber = 0;

	static synchronized int nextNumber() {
		return threadNumber++;
	}

	int myNumber;

	private class Runner implements Runnable {
		public Runner() {
			myNumber = nextNumber();
		}

		public void run() {
			startEating();
		}
	};

	public void eat() throws Exception {
		new Thread(new Runner()).start();
	}

	private synchronized void startEating() {
		state = State.WAITING;
		starvationTimer = EAT_DEADLINE;
		leftFork.grab();
		rightFork.grab();
		state = State.EATING;
	}

	private synchronized void doneEating() {
		leftFork.drop();
		rightFork.drop();
		state = State.THINKING;
	}

	public void tic() {
		switch (state) {
		case EATING:
			doneEating();
			break;
		case THINKING:
			break;
		case WAITING:
			stillWaitingToEat();
			break;
		}
	}

	public boolean isAlive() {
		return isAlive;
	}
}
